home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / ViePratique / ArchiFacile / ArchiFacileSetup.exe / {app} / nw.pak / Unnamed File 000128.txt < prev    next >
Text File  |  2014-10-14  |  11KB  |  365 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. cr.define('cr.ui', function() {
  6.   /** @const */ var EventTarget = cr.EventTarget;
  7.  
  8.   /**
  9.    * Creates a new selection model that is to be used with lists.
  10.    *
  11.    * @param {number=} opt_length The number items in the selection.
  12.    *
  13.    * @constructor
  14.    * @extends {!cr.EventTarget}
  15.    */
  16.   function ListSelectionModel(opt_length) {
  17.     this.length_ = opt_length || 0;
  18.     // Even though selectedIndexes_ is really a map we use an array here to get
  19.     // iteration in the order of the indexes.
  20.     this.selectedIndexes_ = [];
  21.  
  22.     // True if any item could be lead or anchor. False if only selected ones.
  23.     this.independentLeadItem_ = !cr.isMac && !cr.isChromeOS;
  24.   }
  25.  
  26.   ListSelectionModel.prototype = {
  27.     __proto__: EventTarget.prototype,
  28.  
  29.     /**
  30.      * The number of items in the model.
  31.      * @type {number}
  32.      */
  33.     get length() {
  34.       return this.length_;
  35.     },
  36.  
  37.     /**
  38.      * The selected indexes.
  39.      * Setter also changes lead and anchor indexes if value list is nonempty.
  40.      * @type {!Array}
  41.      */
  42.     get selectedIndexes() {
  43.       return Object.keys(this.selectedIndexes_).map(Number);
  44.     },
  45.     set selectedIndexes(selectedIndexes) {
  46.       this.beginChange();
  47.       var unselected = {};
  48.       for (var index in this.selectedIndexes_) {
  49.         unselected[index] = true;
  50.       }
  51.  
  52.       for (var i = 0; i < selectedIndexes.length; i++) {
  53.         var index = selectedIndexes[i];
  54.         if (index in this.selectedIndexes_) {
  55.           delete unselected[index];
  56.         } else {
  57.           this.selectedIndexes_[index] = true;
  58.           // Mark the index as changed. If previously marked, then unmark,
  59.           // since it just got reverted to the original state.
  60.           if (index in this.changedIndexes_)
  61.             delete this.changedIndexes_[index];
  62.           else
  63.             this.changedIndexes_[index] = true;
  64.         }
  65.       }
  66.  
  67.       for (var index in unselected) {
  68.         delete this.selectedIndexes_[index];
  69.         // Mark the index as changed. If previously marked, then unmark,
  70.         // since it just got reverted to the original state.
  71.         if (index in this.changedIndexes_)
  72.           delete this.changedIndexes_[index];
  73.         else
  74.           this.changedIndexes_[index] = false;
  75.       }
  76.  
  77.       if (selectedIndexes.length) {
  78.         this.leadIndex = this.anchorIndex = selectedIndexes[0];
  79.       } else {
  80.         this.leadIndex = this.anchorIndex = -1;
  81.       }
  82.       this.endChange();
  83.     },
  84.  
  85.     /**
  86.      * Convenience getter which returns the first selected index.
  87.      * Setter also changes lead and anchor indexes if value is nonnegative.
  88.      * @type {number}
  89.      */
  90.     get selectedIndex() {
  91.       for (var i in this.selectedIndexes_) {
  92.         return Number(i);
  93.       }
  94.       return -1;
  95.     },
  96.     set selectedIndex(selectedIndex) {
  97.       this.selectedIndexes = selectedIndex != -1 ? [selectedIndex] : [];
  98.     },
  99.  
  100.     /**
  101.      * Returns the nearest selected index or -1 if no item selected.
  102.      * @param {number} index The origin index.
  103.      * @type {number}
  104.      * @private
  105.      */
  106.     getNearestSelectedIndex_: function(index) {
  107.       if (index == -1)
  108.         return -1;
  109.  
  110.       var result = Infinity;
  111.       for (var i in this.selectedIndexes_) {
  112.         if (Math.abs(i - index) < Math.abs(result - index))
  113.           result = i;
  114.       }
  115.       return result < this.length ? Number(result) : -1;
  116.     },
  117.  
  118.     /**
  119.      * Selects a range of indexes, starting with {@code start} and ends with
  120.      * {@code end}.
  121.      * @param {number} start The first index to select.
  122.      * @param {number} end The last index to select.
  123.      */
  124.     selectRange: function(start, end) {
  125.       // Swap if starts comes after end.
  126.       if (start > end) {
  127.         var tmp = start;
  128.         start = end;
  129.         end = tmp;
  130.       }
  131.  
  132.       this.beginChange();
  133.  
  134.       for (var index = start; index != end; index++) {
  135.         this.setIndexSelected(index, true);
  136.       }
  137.       this.setIndexSelected(end, true);
  138.  
  139.       this.endChange();
  140.     },
  141.  
  142.     /**
  143.      * Selects all indexes.
  144.      */
  145.     selectAll: function() {
  146.       this.selectRange(0, this.length - 1);
  147.     },
  148.  
  149.     /**
  150.      * Clears the selection
  151.      */
  152.     clear: function() {
  153.       this.beginChange();
  154.       this.length_ = 0;
  155.       this.anchorIndex = this.leadIndex = -1;
  156.       this.unselectAll();
  157.       this.endChange();
  158.     },
  159.  
  160.     /**
  161.      * Unselects all selected items.
  162.      */
  163.     unselectAll: function() {
  164.       this.beginChange();
  165.       for (var i in this.selectedIndexes_) {
  166.         this.setIndexSelected(i, false);
  167.       }
  168.       this.endChange();
  169.     },
  170.  
  171.     /**
  172.      * Sets the selected state for an index.
  173.      * @param {number} index The index to set the selected state for.
  174.      * @param {boolean} b Whether to select the index or not.
  175.      */
  176.     setIndexSelected: function(index, b) {
  177.       var oldSelected = index in this.selectedIndexes_;
  178.       if (oldSelected == b)
  179.         return;
  180.  
  181.       if (b)
  182.         this.selectedIndexes_[index] = true;
  183.       else
  184.         delete this.selectedIndexes_[index];
  185.  
  186.       this.beginChange();
  187.  
  188.       this.changedIndexes_[index] = b;
  189.  
  190.       // End change dispatches an event which in turn may update the view.
  191.       this.endChange();
  192.     },
  193.  
  194.     /**
  195.      * Whether a given index is selected or not.
  196.      * @param {number} index The index to check.
  197.      * @return {boolean} Whether an index is selected.
  198.      */
  199.     getIndexSelected: function(index) {
  200.       return index in this.selectedIndexes_;
  201.     },
  202.  
  203.     /**
  204.      * This is used to begin batching changes. Call {@code endChange} when you
  205.      * are done making changes.
  206.      */
  207.     beginChange: function() {
  208.       if (!this.changeCount_) {
  209.         this.changeCount_ = 0;
  210.         this.changedIndexes_ = {};
  211.         this.oldLeadIndex_ = this.leadIndex_;
  212.         this.oldAnchorIndex_ = this.anchorIndex_;
  213.       }
  214.       this.changeCount_++;
  215.     },
  216.  
  217.     /**
  218.      * Call this after changes are done and it will dispatch a change event if
  219.      * any changes were actually done.
  220.      */
  221.     endChange: function() {
  222.       this.changeCount_--;
  223.       if (!this.changeCount_) {
  224.         // Calls delayed |dispatchPropertyChange|s, only when |leadIndex| or
  225.         // |anchorIndex| has been actually changed in the batch.
  226.         this.leadIndex_ = this.adjustIndex_(this.leadIndex_);
  227.         if (this.leadIndex_ != this.oldLeadIndex_) {
  228.           cr.dispatchPropertyChange(this, 'leadIndex',
  229.                                     this.leadIndex_, this.oldLeadIndex_);
  230.         }
  231.         this.oldLeadIndex_ = null;
  232.  
  233.         this.anchorIndex_ = this.adjustIndex_(this.anchorIndex_);
  234.         if (this.anchorIndex_ != this.oldAnchorIndex_) {
  235.           cr.dispatchPropertyChange(this, 'anchorIndex',
  236.                                     this.anchorIndex_, this.oldAnchorIndex_);
  237.         }
  238.         this.oldAnchorIndex_ = null;
  239.  
  240.         var indexes = Object.keys(this.changedIndexes_);
  241.         if (indexes.length) {
  242.           var e = new Event('change');
  243.           e.changes = indexes.map(function(index) {
  244.             return {
  245.               index: Number(index),
  246.               selected: this.changedIndexes_[index]
  247.             };
  248.           }, this);
  249.           this.dispatchEvent(e);
  250.         }
  251.         this.changedIndexes_ = {};
  252.       }
  253.     },
  254.  
  255.     leadIndex_: -1,
  256.     oldLeadIndex_: null,
  257.  
  258.     /**
  259.      * The leadIndex is used with multiple selection and it is the index that
  260.      * the user is moving using the arrow keys.
  261.      * @type {number}
  262.      */
  263.     get leadIndex() {
  264.       return this.leadIndex_;
  265.     },
  266.     set leadIndex(leadIndex) {
  267.       var oldValue = this.leadIndex_;
  268.       var newValue = this.adjustIndex_(leadIndex);
  269.       this.leadIndex_ = newValue;
  270.       // Delays the call of dispatchPropertyChange if batch is running.
  271.       if (!this.changeCount_ && newValue != oldValue)
  272.         cr.dispatchPropertyChange(this, 'leadIndex', newValue, oldValue);
  273.     },
  274.  
  275.     anchorIndex_: -1,
  276.     oldAnchorIndex_: null,
  277.  
  278.     /**
  279.      * The anchorIndex is used with multiple selection.
  280.      * @type {number}
  281.      */
  282.     get anchorIndex() {
  283.       return this.anchorIndex_;
  284.     },
  285.     set anchorIndex(anchorIndex) {
  286.       var oldValue = this.anchorIndex_;
  287.       var newValue = this.adjustIndex_(anchorIndex);
  288.       this.anchorIndex_ = newValue;
  289.       // Delays the call of dispatchPropertyChange if batch is running.
  290.       if (!this.changeCount_ && newValue != oldValue)
  291.         cr.dispatchPropertyChange(this, 'anchorIndex', newValue, oldValue);
  292.     },
  293.  
  294.     /**
  295.      * Helper method that adjustes a value before assiging it to leadIndex or
  296.      * anchorIndex.
  297.      * @param {number} index New value for leadIndex or anchorIndex.
  298.      * @return {number} Corrected value.
  299.      */
  300.     adjustIndex_: function(index) {
  301.       index = Math.max(-1, Math.min(this.length_ - 1, index));
  302.       // On Mac and ChromeOS lead and anchor items are forced to be among
  303.       // selected items. This rule is not enforces until end of batch update.
  304.       if (!this.changeCount_ && !this.independentLeadItem_ &&
  305.           !this.getIndexSelected(index)) {
  306.         var index2 = this.getNearestSelectedIndex_(index);
  307.         index = index2;
  308.       }
  309.       return index;
  310.     },
  311.  
  312.     /**
  313.      * Whether the selection model supports multiple selected items.
  314.      * @type {boolean}
  315.      */
  316.     get multiple() {
  317.       return true;
  318.     },
  319.  
  320.     /**
  321.      * Adjusts the selection after reordering of items in the table.
  322.      * @param {!Array.<number>} permutation The reordering permutation.
  323.      */
  324.     adjustToReordering: function(permutation) {
  325.       this.beginChange();
  326.       var oldLeadIndex = this.leadIndex;
  327.       var oldAnchorIndex = this.anchorIndex;
  328.       var oldSelectedItemsCount = this.selectedIndexes.length;
  329.  
  330.       this.selectedIndexes = this.selectedIndexes.map(function(oldIndex) {
  331.         return permutation[oldIndex];
  332.       }).filter(function(index) {
  333.         return index != -1;
  334.       });
  335.  
  336.       // Will be adjusted in endChange.
  337.       if (oldLeadIndex != -1)
  338.         this.leadIndex = permutation[oldLeadIndex];
  339.       if (oldAnchorIndex != -1)
  340.         this.anchorIndex = permutation[oldAnchorIndex];
  341.  
  342.       if (oldSelectedItemsCount && !this.selectedIndexes.length &&
  343.           this.length_ && oldLeadIndex != -1) {
  344.         // All selected items are deleted. We move selection to next item of
  345.         // last selected item.
  346.         this.selectedIndexes = [Math.min(oldLeadIndex, this.length_ - 1)];
  347.       }
  348.  
  349.       this.endChange();
  350.     },
  351.  
  352.     /**
  353.      * Adjusts selection model length.
  354.      * @param {number} length New selection model length.
  355.      */
  356.     adjustLength: function(length) {
  357.       this.length_ = length;
  358.     }
  359.   };
  360.  
  361.   return {
  362.     ListSelectionModel: ListSelectionModel
  363.   };
  364. });
  365.